// 异步模式

// 异步模式的api不会等待这个任务的结束才开始下一个任务
// 耗时任务开启后就立即往后执行下一个任务，耗时任务后续逻辑一般会通过回调函数的方式定义
// 单线程的javascript语言无法同时处理大量耗时任务
// 代码执行顺序混乱

console.log('global begin');

setTimeout(function timer1() {
    console.log('timer1 invoke');
}, 1800)

setTimeout(function timer2() {
    console.log('timer2 invoke');
    setTimeout(function inner() {
        console.log('innvoke inner');
    }, 1000)
}, 1000)

console.log('global end');

// 调用栈(call stack)、WebApis、消息队列(Queue)、Event Loop

// 执行解析
// 1、遇到log，压栈 ==> 执行输出 ==> 出栈

// 2、定时器压栈 ==> 开启timer1定时器，timer1 放进 WebAPIS，倒计时器是单独工作的不会受js影响 ==> 定时器执行完出栈

// 3、又一个定时器，原理同上

// 4、遇到log，压栈 ==> 执行输出 ==> 出栈

// 5、此时调用栈没有任务，event Loop发挥作用，只监听调用栈和消息队列，当调用栈所有任务结束，它将会从消息队列取出第一个任务压入调用栈

// 6、timer2倒计时时间比timer1短，timer2倒计时结束后将放入消息队列第一位，timer倒计时结束后放入消息队列第二位；如果消息队列发生变化，Event Loop就会监听到，把消息队列的第一个取出 压入调用栈继续执行；
// 6、a：遇到log，压栈 ==> 执行输出 ==> 出栈；
// 6、b：遇到定时器，原理同第二步。如此反复，直到调用栈和消息队列没有需要执行的任务整体代码就结束

// 调用栈理解为正在执行的工作表，消息队列就理解为待办工作表
// js引擎先做完待办的任务，再通过事件循环从消息队列中再取一个任务出来继续执行，以此类推
// 随时可以往消息队列中放入任务，这些任务在消息队列中排队等待事件循环
// 整个过程通过内部的消息队列和事件循环实现

// 因为这里分开分析，可能就得他们有先后顺序，但是不是这样的，
// 其实他们各自有各自的时间线
// 如：定时器开启后不会管调用栈和消息队列中是什么情况

// js是单线程的但是浏览器不是单线程的，通过js调用的内部api不是单线程的，如计时器，内部有一个单独的线程执行计时器，时间到了就把回调放到消息队列

// 单线程指执行我们代码的线程
// 内部的api会用单独的线程执行等待的操作

// 运行环境提供的API是以同步或异步模式的方式工作
// 异步任务下达这个任务开始的指令就会继续往下执行，代码不会等待该行代码执行结束